using System;
using System.Collections.Generic;
using System.Collections;
using UnityEngine;

// event manager singleton params template
public class EventMgr : Singleton<EventMgr>
{
    // event dictionary
    private Dictionary<string, Delegate> eventDic = new Dictionary<string, Delegate>();

    // add event
    public void On(string eventName, Action action)
    {
        if (!eventDic.ContainsKey(eventName))
        {
            eventDic.Add(eventName, null);
        }
        eventDic[eventName] = (Action)eventDic[eventName] + action;
    }

    public void On<T>(string eventName, Action<T> action)
    {
        if (!eventDic.ContainsKey(eventName))
        {
            eventDic.Add(eventName, null);
        }
        eventDic[eventName] = (Action<T>)eventDic[eventName] + action;
    }

    public void On<T,T1>(string eventName, Action<T,T1> action)
    {
        if (!eventDic.ContainsKey(eventName))
        {
            eventDic.Add(eventName, null);
        }
        eventDic[eventName] = (Action<T,T1>)eventDic[eventName] + action;
    }

    public void On<T,T1,T2>(string eventName, Action<T,T1,T2> action)
    {
        if (!eventDic.ContainsKey(eventName))
        {
            eventDic.Add(eventName, null);
        }
        eventDic[eventName] = (Action<T,T1,T2>)eventDic[eventName] + action;
    }

    public void On<T,T1,T2,T3>(string eventName, Action<T,T1,T2,T3> action)
    {
        if (!eventDic.ContainsKey(eventName))
        {
            eventDic.Add(eventName, null);
        }
        eventDic[eventName] = (Action<T,T1,T2,T3>)eventDic[eventName] + action;
    }

    // remove event
    public void Off(string eventName, Action action)
    {
        if (eventDic.ContainsKey(eventName))
        {
            eventDic[eventName] = (Action)eventDic[eventName] - action;
            if (eventDic[eventName] == null)
            {
                eventDic.Remove(eventName);
            }
        }
    }

    public void Off<T>(string eventName, Action<T> action)
    {
        if (eventDic.ContainsKey(eventName))
        {
            eventDic[eventName] = (Action<T>)eventDic[eventName] - action;
            if (eventDic[eventName] == null)
            {
                eventDic.Remove(eventName);
            }
        }
    }

    public void Off<T,T1>(string eventName, Action<T,T1> action)
    {
        if (eventDic.ContainsKey(eventName))
        {
            eventDic[eventName] = (Action<T,T1>)eventDic[eventName] - action;
            if (eventDic[eventName] == null)
            {
                eventDic.Remove(eventName);
            }
        }
    }

    public void Off<T,T1,T2>(string eventName, Action<T,T1,T2> action)
    {
        if (eventDic.ContainsKey(eventName))
        {
            eventDic[eventName] = (Action<T,T1,T2>)eventDic[eventName] - action;
            if (eventDic[eventName] == null)
            {
                eventDic.Remove(eventName);
            }
        }
    }

    public void Off<T,T1,T2,T3>(string eventName, Action<T,T1,T2,T3> action)
    {
        if (eventDic.ContainsKey(eventName))
        {
            eventDic[eventName] = (Action<T,T1,T2,T3>)eventDic[eventName] - action;
            if (eventDic[eventName] == null)
            {
                eventDic.Remove(eventName);
            }
        }
    }

    // trigger event
    public void Fire(string eventName)
    {
        if (eventDic.ContainsKey(eventName))
        {
            Delegate d;
            if (eventDic.TryGetValue(eventName, out d))
            {
                Action callback = d as Action;
                if (callback != null)
                {
                    callback.Invoke();
                }
            }
        }
    }

    public void Fire<T>(string eventName, T arg)
    {
        if (eventDic.ContainsKey(eventName))
        {
            Delegate d;
            if (eventDic.TryGetValue(eventName, out d))
            {
                Action<T> callback = d as Action<T>;
                if (callback != null)
                {
                    callback(arg);
                }
            }
        }
    }

    public void Fire<T,T1>(string eventName, T arg ,T1 arg1)
    {
        if (eventDic.ContainsKey(eventName))
        {
            Delegate d;
            if (eventDic.TryGetValue(eventName, out d))
            {
                Action<T,T1> callback = d as Action<T,T1>;
                if (callback != null)
                {
                    callback.Invoke(arg,arg1);
                }
            }
        }
    }

    public void Fire<T,T1,T2>(string eventName, T arg ,T1 arg1,T2 arg2)
    {
        if (eventDic.ContainsKey(eventName))
        {
            Delegate d;
            if (eventDic.TryGetValue(eventName, out d))
            {
                Action<T,T1,T2> callback = d as Action<T,T1,T2>;
                if (callback != null)
                {
                    callback.Invoke(arg,arg1,arg2);
                }
            }
        }
    }

    public void Fire<T,T1,T2,T3>(string eventName, T arg ,T1 arg1,T2 arg2,T3 arg3)
    {
        if (eventDic.ContainsKey(eventName))
        {
            Delegate d;
            if (eventDic.TryGetValue(eventName, out d))
            {
                Action<T,T1,T2,T3> callback = d as Action<T,T1,T2,T3>;
                if (callback != null)
                {
                    callback.Invoke(arg,arg1,arg2,arg3);
                }
            }
        }
    }
}
